package com.cloud.freeflow.common.filter;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;

import com.cloud.freeflow.common.context.HumanSession;
import com.cloud.freeflow.common.utils.SessionHelper;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;

@WebFilter(filterName = "webSecurityFilter", urlPatterns = "/*")
public class WebSecurityFilter implements Filter {

	@Value("${jwt.secret}")
	public String secret;

	private static final String UNAUTHORIZED = "{\"code\": \"401\",\"msg\": \"401 Unauthorized.\"}";
	private static final String INTERFACE_URL = "/interface/"; // 各子系统服务之间使用
	private static final String STATIC_URL = "/static/"; // 为第三方请求预留

	@Override
	public void init(FilterConfig config) throws ServletException {
	}

	@Override
	public void destroy() {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest servletRequest = (HttpServletRequest) request;
		String requestUrl = servletRequest.getRequestURL().toString();
		HumanSession info = null;
		if (requestUrl.indexOf(INTERFACE_URL) >= 0 || requestUrl.indexOf(STATIC_URL) >= 0) {
			info = new HumanSession();
		} else {
			String token = servletRequest.getHeader("Authorization");
			info = parserClaims(token);
			if (StringUtils.isEmpty(token) || null == info) {
				HttpServletResponse servletResponse = (HttpServletResponse) response;
				servletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
				servletResponse.setHeader("Content-Type", "application/json;charset=UTF-8");
				servletResponse.getOutputStream().write(UNAUTHORIZED.getBytes(StandardCharsets.UTF_8));
				return;
			}
		}
		SessionHelper.set(info);
		chain.doFilter(request, response);
		SessionHelper.clear();
	}

	private HumanSession parserClaims(String token) {
		if (StringUtils.isEmpty(token))
			return null;
		HumanSession session = null;
		try {
			Claims claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
			session = new HumanSession();
			Integer humanId = claims.get(HumanSession.HUMAN_ID, Integer.class);
			if (null != humanId) {
				session.setHumanId(Long.valueOf(humanId));
			}
			session.setHumanName(claims.get(HumanSession.HUMAN_NAME, String.class));
			Integer unitId = claims.get(HumanSession.UNIT_ID, Integer.class);
			if (null != unitId) {
				session.setUnitId(Long.valueOf(unitId));
			}
			session.setUnitName(claims.get(HumanSession.UNIT_NAME, String.class));
			session.setUnitCode(claims.get(HumanSession.UNIT_CODE, String.class));
			String roleIds = claims.get(HumanSession.ROLE_IDS, String.class);
			if (!StringUtils.isEmpty(roleIds)) {
				List<Long> rIds = new ArrayList<Long>();
				String[] ts = roleIds.split(",");
				for (String id : ts) {
					rIds.add(Long.valueOf(id));
				}
				session.setRoleIds(rIds);
			}

		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return session;
	}

}
